/*
 * Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.igitalExplorer.SketchDemo.fragment.work.distance;

import static com.xuexiang.xutil.XUtil.runOnUiThread;

import android.annotation.SuppressLint;
import android.os.Build;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.JavascriptInterface;
import android.webkit.ValueCallback;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;

import com.clj.fastble.BleManager;
import com.clj.fastble.callback.BleNotifyCallback;
import com.clj.fastble.callback.BleWriteCallback;
import com.clj.fastble.data.BleDevice;
import com.clj.fastble.exception.BleException;
import com.google.gson.Gson;
import com.igitalExplorer.SketchDemo.R;
import com.igitalExplorer.SketchDemo.activity.MainActivity;
import com.igitalExplorer.SketchDemo.adapter.comm.Observer;
import com.igitalExplorer.SketchDemo.bean.DistanceJson;
import com.igitalExplorer.SketchDemo.core.BaseFragment;
import com.igitalExplorer.SketchDemo.databinding.FragmentLeftDistanceBinding;
import com.igitalExplorer.SketchDemo.fragment.work.side.SideFragment;
import com.igitalExplorer.SketchDemo.utils.DrawUtils;
import com.igitalExplorer.SketchDemo.utils.FileUtils;
import com.igitalExplorer.SketchDemo.utils.MMKVUtils;
import com.igitalExplorer.SketchDemo.utils.XToastUtils;
import com.xuexiang.xpage.annotation.Page;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

/**
 * @author zhangliang
 * @since 2021-12-13 21:49
 */
@Page(name = "左帮+迎头测量")
public class LeftDistanceFragment extends BaseFragment<FragmentLeftDistanceBinding> implements View.OnClickListener, Observer {
    //uuid默认服务码
    String uuid_service = "0000FFE0-0000-1000-8000-00805F9B34FB";
    String uuid_characteristic_write = "0000FFE1-0000-1000-8000-00805F9B34FB";
    String uuid_characteristic_notify = "0000FFE1-0000-1000-8000-00805F9B34FB";
    private BleDevice bleDevice;
    //private final StringBuffer appendString = new StringBuffer();
    private String distanceJson = "";
    private double distance = 0;
    private double height = 0;
    private double tempDistance = 0;

    @NonNull
    @Override
    protected FragmentLeftDistanceBinding viewBindingInflate(LayoutInflater inflater, ViewGroup container) {
        return FragmentLeftDistanceBinding.inflate(inflater, container, false);
    }

    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    @Override
    protected void initViews() {
        //从MMKV取蓝牙键
        bleDevice = MMKVUtils.getObject(MainActivity.KEY_BLUETOOTH, BleDevice.class, null);
        if (bleDevice == null) {
            XToastUtils.toast("请先连接蓝牙！");
            popToBack();
        }

        binding.btnControl.setText(getText(R.string.start_distance));
        binding.btnContinue.setText(getText(R.string.pause_distance));

        initWebView();

        initBle();
    }

    @Override
    protected void initListeners() {
        binding.btnControl.setOnClickListener(this);
        binding.btnContinue.setOnClickListener(this);
        binding.btnDeleteData.setOnClickListener(this);
        binding.btnSwitchSideMode.setOnClickListener(this);
        binding.btnCheckZero.setOnClickListener(this);
    }

    @SuppressLint({"JavascriptInterface", "SetJavaScriptEnabled"})
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    private void initWebView() {
        //初始前端控件
        binding.distanceWebView.getSettings().setJavaScriptEnabled(true);
        // 设置是否可缩放
        binding.distanceWebView.getSettings().setSupportZoom(true);
        binding.distanceWebView.getSettings().setBuiltInZoomControls(true);
        WebView.setWebContentsDebuggingEnabled(true);
        binding.distanceWebView.addJavascriptInterface(this, "Distance");
        binding.distanceWebView.loadUrl("file:///android_asset/Distance.html");
        binding.distanceWebView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
                return true;
            }
        });
    }

    /**
     * 初始化蓝牙，蓝牙连接对象来自于 MainActivity Intent传递而来
     */
    private void initBle() {
        /*
        开始通知，通知的 uuid数据来自于芯片文档
         */
        BleManager.getInstance().notify(bleDevice, uuid_service, uuid_characteristic_notify, new BleNotifyCallback() {
            @Override
            public void onNotifySuccess() {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {

                    }
                });
            }

            @Override
            public void onNotifyFailure(final BleException exception) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {

                    }
                });
            }

            /*
            蓝牙模块发送给APP数据 调用的方法 data即比特数组
             */
            @Override
            public void onCharacteristicChanged(final byte[] data) {
                runOnUiThread(new Runnable() {
                    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
                    @SuppressLint("SetTextI18n")
                    @Override
                    public void run() {
                        String str = new String(data);
                        String[] distanceStr = str.split("C7");
                        for (String string : distanceStr) {
                            if (string.length() == 34) {
                                //得到的当前距离
                                double getDistance = Double.parseDouble(string.substring(4, 10) + "." + string.substring(10, 12));
                                double differenceDistance = getDistance - tempDistance;
                                if (differenceDistance <= 0) {
                                    break;
                                }
                                //如果能通过差值判断，将得到的值放到下一个循环
                                tempDistance = getDistance;
                                double getSlope;
                                //判断坡度是否为负
                                if (string.charAt(12) == '1') {
                                    getSlope = Double.parseDouble("-" + string.substring(13, 16) + "." + string.substring(16, 18));
                                } else {
                                    getSlope = Double.parseDouble(string.substring(13, 16) + "." + string.substring(16, 18));
                                }
                                //将角度转为弧度(java传入的是弧度值)
                                double slope = DrawUtils.radianConverse(getSlope);
                                //横距值(距离*cos坡度值)，保留两位小数
                                distance += differenceDistance * Math.cos(slope);
                                //高程值(距离*sin坡度值)，保留两位小数
                                height += differenceDistance * Math.sin(slope);
                                double getRoll;
                                //判断横滚是否为负
                                if (string.charAt(18) == '1') {
                                    getRoll = Double.parseDouble("-" + string.substring(19, 22) + "." + string.substring(22, 24));
                                } else {
                                    getRoll = Double.parseDouble(string.substring(19, 22) + "." + string.substring(22, 24));
                                }
                                binding.distanceText.setText("接收距离:" + DrawUtils.getDoubleScale(getDistance, 2) + "; 接收坡度:" + DrawUtils.getDoubleScale(getSlope, 2) + "; 接收横滚:" + DrawUtils.getDoubleScale(getRoll, 2)
                                        + "; 距离差值:" + DrawUtils.getDoubleScale(differenceDistance, 2) + "; 横距:" + DrawUtils.getDoubleScale(distance, 2) + "; 高程:" + DrawUtils.getDoubleScale(height, 2));
                                distanceJson = new Gson().toJson(new DistanceJson(DrawUtils.getDoubleScale(distance, 3), DrawUtils.getDoubleScale(height, 3)));
                                binding.distanceWebView.evaluateJavascript("javascript:reloadData()", new ValueCallback<String>() {
                                    @Override
                                    public void onReceiveValue(String value) {
                                    }
                                });
                                //appendString.append(DrawUtils.getDoubleScale(distance, 1)).append("  ").append(DrawUtils.getDoubleScale(height, 1)).append("\r\n");
                            }
                        }

                        //通用上行数据响应失败（查看文档）
                        if (str.equals("C60206222A6C") || str.equals("C60A062A3A6C") || str.equals("C60306232C6C") || str.equals("C6090629386C") || str.equals("C6010621286C")
                                || str.equals("C60406242E6C") || str.equals("C60B062B3C6C")) {
                            XToastUtils.toast(getString(R.string.msg_data_error));
                        }

                        //通用上行确认模式错误（查看文档）
                        if (str.equals("C60206222A6C") || str.equals("C60A063A4A6C") || str.equals("C60306333C6C") || str.equals("C6090639486C") || str.equals("C60406343E6C")
                                || str.equals("C60B063B4C6C")) {
                            XToastUtils.toast(getString(R.string.msg_mode_error));
                        }

                        //开始测量响应成功
                        if (str.equals("C60206121A6C")) {
                            XToastUtils.toast(getString(R.string.start_success));
                        }

                        //结束测量响应成功
                        if (str.equals("C60A061A2A6C")) {
                            XToastUtils.toast(getString(R.string.stop_success));
                        }

                        //暂停测量响应成功
                        if (str.equals("C60306131C6C")) {
                            XToastUtils.toast("已经暂停测量");
                        }

                        //继续测量响应成功
                        if (str.equals("C6090619286C")) {
                            XToastUtils.toast("正在继续测量...");
                        }

                        //删除测量响应成功
                        if (str.equals("C6010611186C")) {
                            XToastUtils.toast("已经将数据清零");
                        }

                        //侧壁测量响应成功
                        if (str.equals("C60406141E6C")) {
                            XToastUtils.toast("已经切换成侧壁测量模式");
                        }

                        //0°校准响应成功
                        if (str.equals("C60B061B2C6C")) {
                            XToastUtils.toast("0°校准成功");
                        }


                    }
                });
            }
        });
    }

    @SuppressLint("NonConstantResourceId")
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_control:
                if (binding.btnControl.getText().equals(getString(R.string.start_distance))) {
                    sendToBle("C60206020A6C");
                    binding.btnControl.setText(R.string.stop_distance);
                } else if (binding.btnControl.getText().equals(getString(R.string.stop_distance))) {
                    //发送结束指令之前必须发送暂停指令
                    if (binding.btnContinue.getText().equals(getString(R.string.pause_distance))) {
                        XToastUtils.toast("请先暂停距离测量！");
                        break;
                    }
                    sendToBle("C60A060A1A6C");
                    /*String txtString = "平距(米)   高程" + "\r\n";
                    //得到时间戳
                    String currentTxtTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(new Date().getTime());
                    //AndroidManifest中需要开启android:requestLegacyExternalStorage="true"
                    FileUtils.writeTxtToFile(txtString + appendString.toString(), "sdcard/sketch-output/", currentTxtTime + ".txt");*/
                    binding.btnControl.setText(R.string.start_distance);
                }
                break;
            case R.id.btn_continue:
                if (binding.btnContinue.getText().equals(getString(R.string.pause_distance))) {
                    sendToBle("C60306030C6C");
                    binding.btnContinue.setText(R.string.continue_distance);
                } else if (binding.btnContinue.getText().equals(getString(R.string.continue_distance))) {
                    sendToBle("C6090609186C");
                    binding.btnContinue.setText(R.string.pause_distance);
                }
                break;
            case R.id.btn_deleteData:
                sendToBle("C6010601086C");
                break;
            case R.id.btn_checkZero:
                sendToBle("C60B060B1C6C");
                break;
            case R.id.btn_switchSideMode:
                //发送侧壁模式切换指令之前必须发送暂停指令
                if (binding.btnContinue.getText().equals(getString(R.string.pause_distance))) {
                    XToastUtils.toast("请先暂停距离测量！");
                    break;
                }
                sendToBle("C60406040E6C");
                openPage(SideFragment.class);
                break;
        }
    }

    /*
    向Ble发送数据
     */
    public void sendToBle(String sendStr) {
        /*
        把字符串 转变为 HEX
         */
        if (TextUtils.isEmpty(sendStr)) {
            return;
        }
        BleManager.getInstance().write(
                bleDevice,
                uuid_service,
                uuid_characteristic_write,
                sendStr.getBytes(),
                new BleWriteCallback() {
                    @Override
                    public void onWriteSuccess(final int current, final int total,
                                               final byte[] justWrite) {
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                XToastUtils.toast(getString(R.string.msg_send_success));
                            }
                        });

                    }

                    @Override
                    public void onWriteFailure(final BleException exception) {
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                XToastUtils.toast(getString(R.string.msg_send_error));
                            }
                        });
                    }
                });
    }

    @Override
    public void disConnected(BleDevice device) {
        if (device != null && bleDevice != null && device.getKey().equals(bleDevice.getKey())) {
            popToBack();
        }
    }

    @JavascriptInterface
    public String returnDistanceJson() {
        //得到要发送的json
        return distanceJson;
    }
}